package com.example.ams.service;

import com.example.ams.dto.AttendanceSummaryDTO;
import com.example.ams.entity.AttendanceSummary;
import com.example.ams.entity.ClockRecord;
import com.example.ams.entity.Employee;
import com.example.ams.repository.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 考勤统计服务类
 * Attendance Summary Service
 */
@Service
public class AttendanceSummaryService {

    @Autowired
    private AttendanceSummaryRepository summaryRepository;

    @Autowired
    private EmployeeRepository employeeRepository;

    @Autowired
    private ClockRecordRepository clockRecordRepository;

    @Autowired
    private LeaveRecordRepository leaveRecordRepository;

    @Autowired
    private OvertimeRecordRepository overtimeRecordRepository;

    @Autowired
    private TravelRecordRepository travelRecordRepository;

    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    private static final SimpleDateFormat MONTH_FORMAT = new SimpleDateFormat("yyyy-MM");

    /**
     * 查询统计（按员工和月份）
     */
    public AttendanceSummaryDTO getSummary(Long employeeId, String month) {
        if (employeeId != null && month != null) {
            // 查询单个员工单月统计
            return summaryRepository.findByEmployeeIdAndMonth(employeeId, month)
                    .map(this::convertToDTO)
                    .orElse(calculateSummary(employeeId, month));
        } else if (month != null) {
            // 查询所有员工某月统计 - 返回第一个作为示例
            List<AttendanceSummary> summaries = summaryRepository.findByMonth(month);
            if (!summaries.isEmpty()) {
                return convertToDTO(summaries.get(0));
            }
        } else if (employeeId != null) {
            // 查询某员工所有月份统计 - 返回最新一个
            List<AttendanceSummary> summaries = summaryRepository.findByEmployeeIdOrderByMonthDesc(employeeId);
            if (!summaries.isEmpty()) {
                return convertToDTO(summaries.get(0));
            }
        }
        
        throw new RuntimeException("未找到统计数据");
    }

    /**
     * 查询某月所有员工的统计
     */
    public List<AttendanceSummaryDTO> getSummariesByMonth(String month) {
        return summaryRepository.findByMonth(month).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    /**
     * 实时计算统计（如果数据库中没有）
     */
    private AttendanceSummaryDTO calculateSummary(Long employeeId, String month) {
        try {
            Date startDate = MONTH_FORMAT.parse(month);
            Calendar cal = Calendar.getInstance();
            cal.setTime(startDate);
            cal.add(Calendar.MONTH, 1);
            Date endDate = cal.getTime();

            AttendanceSummaryDTO summary = new AttendanceSummaryDTO();
            summary.setEmployeeId(employeeId);
            summary.setMonth(month);

            // 填充员工信息
            employeeRepository.findById(employeeId).ifPresent(emp -> {
                summary.setEmployeeName(emp.getName());
                summary.setEmpNo(emp.getEmpNo());
            });

            // 计算打卡天数（简化：统计有打卡记录的天数）
            List<ClockRecord> clockRecords = clockRecordRepository
                    .findByEmployeeIdAndTimeRange(employeeId, startDate, endDate);
            
            Set<String> workDaysSet = new HashSet<>();
            for (ClockRecord record : clockRecords) {
                workDaysSet.add(DATE_FORMAT.format(record.getEventTime()));
            }
            summary.setWorkDays(workDaysSet.size());

            // 简化统计：迟到、早退、旷工都设为0（完整实现需要对比班次时间）
            summary.setLateCount(0);
            summary.setEarlyCount(0);
            summary.setAbsentCount(0);

            // 统计请假时长
            BigDecimal totalLeaveHours = leaveRecordRepository
                    .findByEmployeeIdAndTimeRange(employeeId, startDate, endDate)
                    .stream()
                    .map(leave -> leave.getHours())
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            summary.setLeaveHours(totalLeaveHours);

            // 统计加班时长
            BigDecimal totalOtHours = overtimeRecordRepository
                    .findByEmployeeIdAndTimeRange(employeeId, startDate, endDate)
                    .stream()
                    .map(ot -> ot.getHours())
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            summary.setOtHours(totalOtHours);

            // 统计出差天数（简化：按记录数计算）
            long travelCount = travelRecordRepository
                    .findByEmployeeIdAndTimeRange(employeeId, startDate, endDate)
                    .size();
            summary.setTravelDays(BigDecimal.valueOf(travelCount));

            return summary;
        } catch (ParseException e) {
            throw new RuntimeException("月份格式错误: " + month);
        }
    }

    /**
     * 重新计算并保存统计
     */
    @Transactional
    public AttendanceSummaryDTO rebuildSummary(Long employeeId, String month) {
        AttendanceSummaryDTO calculated = calculateSummary(employeeId, month);
        
        // 查找是否已存在
        Optional<AttendanceSummary> existing = summaryRepository
                .findByEmployeeIdAndMonth(employeeId, month);
        
        AttendanceSummary summary;
        if (existing.isPresent()) {
            summary = existing.get();
        } else {
            summary = new AttendanceSummary();
            summary.setEmployeeId(employeeId);
            summary.setMonth(month);
        }
        
        summary.setWorkDays(calculated.getWorkDays());
        summary.setLateCount(calculated.getLateCount());
        summary.setEarlyCount(calculated.getEarlyCount());
        summary.setAbsentCount(calculated.getAbsentCount());
        summary.setLeaveHours(calculated.getLeaveHours());
        summary.setOtHours(calculated.getOtHours());
        summary.setTravelDays(calculated.getTravelDays());
        
        AttendanceSummary saved = summaryRepository.save(summary);
        return convertToDTO(saved);
    }

    /**
     * Entity转DTO
     */
    private AttendanceSummaryDTO convertToDTO(AttendanceSummary summary) {
        AttendanceSummaryDTO dto = new AttendanceSummaryDTO();
        BeanUtils.copyProperties(summary, dto);

        // 填充员工信息
        employeeRepository.findById(summary.getEmployeeId()).ifPresent(emp -> {
            dto.setEmployeeName(emp.getName());
            dto.setEmpNo(emp.getEmpNo());
        });

        return dto;
    }
}

